package vg.modules.search.components.additionalAttributesPanel;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashSet;
import java.util.Set;

import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

import vg.services.user_interface_manager.additional_swing_components.TableCellTooltipRender;

/**
 * This class realizes a panel, which contains additional attributes
 * for visualization of new graph.
 * All methods of this class by need called from EDT only!!! 
 * @author tzolotuhin
 */
public class AdditionalAttributePanel {
	// Defines
	private final static int DEF_ROW_HEIGHT = 22;
	// Main components
	private final JPanel view;
	// Data
	private Set<String>vertexAttributes = null;
	// Mutex
	private final Object theObjectMutex = new Object();
	// Swing components
	private JTable table;
	private JScrollPane scroll;
	private JCheckBox selectAll;
	private JLabel selectAllLabel;
	/**
	 * Constructor.
	 */
	public AdditionalAttributePanel() {
		//build interface components
		this.view = new JPanel(new GridBagLayout());
		this.selectAll = new JCheckBox();
		this.selectAllLabel = new JLabel("Select all :");
		this.selectAll.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				synchronized (theObjectMutex) {
					JCheckBox src = (JCheckBox)e.getSource();
					boolean check = src.isSelected();
					for(int i = 0 ; i < table.getRowCount() ; i++) {
						table.setValueAt(check, i, 0);
					}
					table.editingStopped(null);
					table.updateUI();											
				}
			}
		});
	}
	/**
	 * This method sets new vertex attributes.
	 * @param vertexAttributes - is set of vertex attributes.
	 */
	public void setVertexAttributes(final Set<String>vertexAttributes) {
		synchronized (theObjectMutex) {			
			if(this.vertexAttributes != vertexAttributes) {
				this.vertexAttributes = vertexAttributes;
			}
			update();
		}
	}
	/**
	 * This method returns set of addition attributes for vertices.
	 */
	public Set<String> getVertexAdditionalAttributes() {
		synchronized (theObjectMutex) {
			Set<String>data = new HashSet<String>();
			for(int i = 0; i < this.table.getRowCount(); i++) {
				Boolean check = (Boolean)this.table.getValueAt(i, 0);
				if(check != null && check == true) {
					String name = (String)this.table.getValueAt(i, 1);
					if(name != null) {
						data.add(name);
					}
				}
			} // end of vertex cycle 
			return(data);		
		}
	}
	public JPanel getView() {
		return(this.view);
	}
	///////////////////////////////////////////////////////////////////////////
	// PRIVATE METHODS
	///////////////////////////////////////////////////////////////////////////
	/**
	 * This method updates additional attribute panel
	 */
	private void update() {
		// clear panel
		this.view.removeAll();
		// create gbc parameter
		GridBagConstraints gbc = null;
		// add all attributes to panel
		Object[][] data = new Object[0][2];
		if(this.vertexAttributes != null) {
			data = new Object[this.vertexAttributes.size()][2];
			int i = 0;
			for(String buf : this.vertexAttributes) {
				data[i][0] = Boolean.valueOf(false);
				data[i][1] = buf;
				i++;
			}
		}
		AATableModel model = new AATableModel(data, selectAll);
		this.table = new JTable(model);
		this.table.setOpaque(true);
		this.table.setFillsViewportHeight(true);
		this.table.setRowHeight(DEF_ROW_HEIGHT);
		this.table.setAutoCreateRowSorter(true);
		this.table.setShowGrid(true);
		this.table.setDefaultRenderer(String.class, new TableCellTooltipRender());
		//Package of interface-------------------
		this.scroll = new JScrollPane(this.table);
		gbc = new GridBagConstraints(0,0,  2,1,  1,1,  GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5),  0,0);
		this.view.add(this.scroll,gbc);
		
		gbc = new GridBagConstraints(0,1,  1,1,  0,0,  GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 5, 5),  0,0);
		this.view.add(this.selectAllLabel,gbc);

		gbc = new GridBagConstraints(1,1,  1,1,  1,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5),  0,0);
		this.view.add(this.selectAll,gbc);
		this.selectAll.setSelected(false); 
		//---------------------------------------
		this.view.updateUI();
	}
	///////////////////////////////////////////////////////////////////////////
	// PRIVATE CLASSES
	///////////////////////////////////////////////////////////////////////////
	/**
	 * This class realizes model for attribute table
	 * @author tzolotuhin
	 */
	private class AATableModel extends AbstractTableModel {
		private static final long serialVersionUID = 1000L;
		//-------------------------------------------------------------------------
		private String[] columnNames = null;
	    private Object[][] table = null;
	    private JCheckBox selectAll = null;
	    private final static int DEF_COUNT_COLUMN = 2;
		//-------------------------------------------------------------------------
	    public AATableModel(final Object[][] data, final JCheckBox selectAll) {
	    	this.selectAll = selectAll;
	    	this.columnNames = new String[DEF_COUNT_COLUMN];
	    	this.table = data;
	       	this.columnNames = new String[]{"Show", "Atribute name"};
	    }
	    public int getColumnCount() {   	
	    	return(DEF_COUNT_COLUMN);
	    }
	    public int getRowCount() {
	    	return(this.table.length);
	    }
	    public Object getValueAt(int rowIndex, int columnIndex) {
	    	return(this.table[rowIndex][columnIndex]);
	    }
	    public String getColumnName(int column) {
	    	return(this.columnNames[column]);
	    }
	    public Class<?> getColumnClass(int columnIndex) {
	    	if (getRowCount() > 0)
	    		return(this.table[0][columnIndex].getClass());
	    	return null;
	    }
	    public boolean isCellEditable(int rowIndex, int columnIndex) {
	    	if(columnIndex == 0) {
	    		return(true);
	    	}
	    	return(false);
	    }
	    /**
	     * This method sets value in table.
	     * @param value - value.
	     * @param row   - number of row.
	     * @param col   - number of column.
	     */
	    public void setValueAt(Object value, int row, int col) {
			this.table[row][col] = value;
			//checking
	    	if(col == 0) {
	    		boolean check = true;
	    		for(int i = 0 ; i < this.table.length ; i++) {
	    			if((Boolean)this.table[i][0] == false) {
	    				check = false;
	    				break;
	    			}
	    		}
	    		this.selectAll.setSelected(check);
	    		this.selectAll.updateUI();
	    	}
	        fireTableCellUpdated(row, col);
	    }  
	}
}
